#pragma once

#include "../stdafx.h"
#include <DirectXCollision.h>

/*
struct SubMesh
{
	UINT IndexCount = 0;
	UINT StartIndexLocation = 0;
	INT BaseVertexLocation = 0;

	// Bounding box of the geometry defined by this submesh. 
	// This is used in later chapters of the book.
	//DirectX::BoundingBox Bounds;
};
class MeshBase
{
public:
	std::string Name;

	// VBV
	ComPtr<ID3D12Resource> VertexBufferGPU = nullptr;
	// IBV
	ComPtr<ID3D12Resource> IndexBufferGPU = nullptr;

	ComPtr<ID3D12Resource> VertexBufferUploader = nullptr;
	ComPtr<ID3D12Resource> IndexBufferUploader = nullptr;

	D3D12_INDEX_BUFFER_VIEW m_indexBufferView;
	D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView;

	std::unordered_map<std::string, SubMesh> DrawArgs;

	virtual void initBuffers(ID3D12Device*, ID3D12GraphicsCommandList*) = 0;
	void DisposeUploaders();

};

class BoxMesh : public MeshBase
{
	struct Vertex
	{
		XMFLOAT3 position;
		XMFLOAT4 color;
	};
	const Vertex vertices[8] =
	{
		{{1.0f, 1.0f, -1.0f}, {0.8f, 0.3f, 0.3f, 1.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.3f, 0.8f, 0.3f, 1.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.3f, 0.3f, 0.8f, 1.0f}},
		{{-1.0f, 1.0f, -1.0f}, {0.8f, 0.8f, 0.3f, 1.0f}},
		{{1.0f, 1.0f, 1.0f}, {0.8f, 0.3f, 0.3f, 1.0f}},
		{{1.0f, -1.0f, 1.0f}, {0.3f, 0.8f, 0.3f, 1.0f}},
		{{-1.0f, -1.0f, 1.0f}, {0.3f, 0.3f, 0.8f, 1.0f}},
		{{-1.0f, 1.0f, 1.0f}, {0.8f, 0.8f, 0.3f, 1.0f}}
	};
	const uint16_t indices[36] =
	{
		// front
		0,1,3,
		3,1,2,
		// left
		3,2,6,
		3,6,7,
		// right
		0,5,1,
		0,4,5,
		// back
		4,6,5,
		7,6,4,
		// up
		7,0,3,
		7,4,0,
		// down
		1,5,6,
		2,1,6
	};

public:
	void initBuffers(ID3D12Device*, ID3D12GraphicsCommandList*) override;

};
*/

struct SubmeshGeometry
{
	UINT IndexCount = 0;
	UINT StartIndexLocation = 0;
	INT BaseVertexLocation = 0;

	// Bounding box of the geometry defined by this submesh. 
	// This is used in later chapters of the book.
	DirectX::BoundingBox Bounds;
};

struct MeshGeometry
{
	// Give it a name so we can look it up by name.
	std::string Name;

	// System memory copies.  Use Blobs because the vertex/index format can be generic.
	// It is up to the client to cast appropriately.  
	Microsoft::WRL::ComPtr<ID3DBlob> VertexBufferCPU = nullptr;
	Microsoft::WRL::ComPtr<ID3DBlob> IndexBufferCPU = nullptr;

	Microsoft::WRL::ComPtr<ID3D12Resource> VertexBufferGPU = nullptr;
	Microsoft::WRL::ComPtr<ID3D12Resource> IndexBufferGPU = nullptr;

	Microsoft::WRL::ComPtr<ID3D12Resource> VertexBufferUploader = nullptr;
	Microsoft::WRL::ComPtr<ID3D12Resource> IndexBufferUploader = nullptr;

	// Data about the buffers.
	UINT VertexByteStride = 0;
	UINT VertexBufferByteSize = 0;
	DXGI_FORMAT IndexFormat = DXGI_FORMAT_R16_UINT;
	UINT IndexBufferByteSize = 0;

	// A MeshGeometry may store multiple geometries in one vertex/index buffer.
	// Use this container to define the Submesh geometries so we can draw
	// the Submeshes individually.
	std::unordered_map<std::string, SubmeshGeometry> DrawArgs;

	D3D12_VERTEX_BUFFER_VIEW VertexBufferView()const
	{
		D3D12_VERTEX_BUFFER_VIEW vbv;
		vbv.BufferLocation = VertexBufferGPU->GetGPUVirtualAddress();
		vbv.StrideInBytes = VertexByteStride;
		vbv.SizeInBytes = VertexBufferByteSize;

		return vbv;
	}

	D3D12_INDEX_BUFFER_VIEW IndexBufferView()const
	{
		D3D12_INDEX_BUFFER_VIEW ibv;
		ibv.BufferLocation = IndexBufferGPU->GetGPUVirtualAddress();
		ibv.Format = IndexFormat;
		ibv.SizeInBytes = IndexBufferByteSize;

		return ibv;
	}

	// We can free this memory after we finish upload to the GPU.
	void DisposeUploaders()
	{
		VertexBufferUploader = nullptr;
		IndexBufferUploader = nullptr;
	}
};